#ifndef _SPI_NOR_CMD_H_
#define _SPI_NOR_CMD_H_

#include "stdint.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define SPI_NOR_ST_DRV_POS 21	   
#define SPI_NOR_ST_QE_POS 9		   
#define SPI_NOR_ST_LB_POS 11	   
#define SPI_NOR_ST_ADDR_MODE_POS 8 

#define SPI_NOR_ST_BUSY_MASK 0x01
#define SPI_NOR_ST_WRITE_EN 0x02

#define SPI_NOR_CMD_Write_Enable 0x06
#define SPI_NOR_CMD_Write_Disable 0x04
#define SPI_NOR_CMD_SRWrite_Enable 0x50

#define SPI_NOR_CMD_Read_StReg1 0x05
#define SPI_NOR_CMD_Read_StReg2 0x35
#define SPI_NOR_CMD_Read_StReg3 0x15
#define SPI_NOR_CMD_Write_StReg1 0x01
#define SPI_NOR_CMD_Write_StReg2 0x31
#define SPI_NOR_CMD_Write_StReg3 0x11

#define SPI_NOR_CMD_Chip_Erase 0x60
#define SPI_NOR_CMD_Enable_Reset 0x66
#define SPI_NOR_CMD_Reset 0x99

#define SPI_NOR_CMD_Read_Identification 0x9F 
#define SPI_NOR_CMD_Read_Device_ID 0x90		 

#define SPI_NOR_CMD_Read_Data 0x03 
#define SPI_NOR_CMD_Fast_Read 0x0B 

#define SPI_NOR_CMD_Quad_Read 0x6B	  
#define SPI_NOR_CMD_Quad_Read_QA 0xEB 

#define SPI_NOR_CMD_Page_Program 0x02	   
#define SPI_NOR_CMD_Quad_Page_Program 0x32 

#define SPI_NOR_CMD_Sector_Erase 0x20
#define SPI_NOR_CMD_Block_Erase_32K 0x52
#define SPI_NOR_CMD_Block_Erase_64K 0xD8

#define SPI_NOR_CMD_Erase_SecurityReg 0x44
#define SPI_NOR_CMD_Program_SecurityReg 0x42
#define SPI_NOR_CMD_Read_SecurityReg 0x48

#define SPI_NOR_CMD_A32_Enter_A32 0xB7
#define SPI_NOR_CMD_A32_Exit_A32 0xE9
#define SPI_NOR_CMD_A32_Set_Addr_MB 0xC5
#define SPI_NOR_CMD_A32_Get_Addr_MB 0xC8

#define SPI_NOR_CMD_A32_Sector_Erase 0x21
#define SPI_NOR_CMD_A32_Block_Erase_32K 0x5C
#define SPI_NOR_CMD_A32_Block_Erase_64K 0xDC

#define SPI_NOR_CMD_A32_Read_Data 0x13	  
#define SPI_NOR_CMD_A32_Fast_Read 0x0C	  
#define SPI_NOR_CMD_A32_Page_Program 0x12 

#define SPI_NOR_CMD_A32_Quad_Read 0x6C		   
#define SPI_NOR_CMD_A32_Quad_Read_QA 0xEC	   
#define SPI_NOR_CMD_A32_Quad_Page_Program 0x34 

#define SPI_NOR_PAGE_SIZE 0x100
#define SPI_NOR_PAGE_MASK 0xFF
#define SPI_NOR_SECTOR_SIZE 0x1000
#define SPI_NOR_BLOCK32_SIZE 0x8000
#define SPI_NOR_BLOCK64_SIZE 0x10000
#define SPI_NOR_PLANE_SIZE 0x1000000

	typedef struct
	{
		void (*cs)(uint8_t st);
		void (*mode_spi)(void);
		void (*mode_qpi_out)(void);
		void (*mode_qpi_in)(void);
		uint8_t (*spi_rb)(void);
		void (*spi_wb)(uint8_t dataW);
		uint8_t (*spi_write)(const uint8_t *dataw, uint32_t Len);
		uint8_t (*spi_read)(uint8_t *datar, uint32_t Len);
		uint8_t (*qpi_write)(const uint8_t *dataw, uint32_t Len);
		uint8_t (*qpi_read)(uint8_t *datar, uint32_t Len);
	} spi_flash_hal_type;

	uint32_t multi_nor_init(const spi_flash_hal_type *hal, uint8_t qspi_en);

	uint8_t multi_nor_reg_get(const spi_flash_hal_type *hal, char reg);
	uint8_t multi_nor_reg_set(const spi_flash_hal_type *hal, char reg, uint8_t msk, uint8_t val); 

	uint32_t multi_nor_st_read(const spi_flash_hal_type *hal);		
	uint8_t multi_nor_busy(const spi_flash_hal_type *hal);			
	uint8_t multi_nor_wait_for_busy(const spi_flash_hal_type *hal); 

	uint8_t multi_nor_id_read(const spi_flash_hal_type *hal, uint8_t *des);

	void multi_nor_write_enable(const spi_flash_hal_type *hal);
	void multi_nor_write_disable(const spi_flash_hal_type *hal);

	uint8_t multi_nor_sector_erase(const spi_flash_hal_type *hal, uint32_t addr);
	uint8_t multi_nor_block_erase(const spi_flash_hal_type *hal, uint32_t addr);
	uint8_t multi_nor_block64_erase(const spi_flash_hal_type *hal, uint32_t addr);
	uint8_t multi_nor_chip_erase(const spi_flash_hal_type *hal);

	uint8_t multi_nor_read(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		
	uint8_t multi_nor_write(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src); 
	uint8_t multi_nor_write_multi(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

	uint8_t multi_nor_q_read(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		  
	uint8_t multi_nor_qa_read(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		  
	uint8_t multi_nor_q_write(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src); 
	uint8_t multi_nor_q_write_multi(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

	uint8_t multi_nor_security_reg_read(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);
	uint8_t multi_nor_security_reg_write(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);
	uint8_t multi_nor_security_reg_erase(const spi_flash_hal_type *hal, uint32_t addr);

	void multi_nor_cmd_exe(const spi_flash_hal_type *hal, uint8_t cmd);
	void multi_nor_cmd_set(const spi_flash_hal_type *hal, uint8_t cmd, uint8_t par);
	uint8_t multi_nor_cmd_get(const spi_flash_hal_type *hal, uint8_t cmd);

	uint8_t multi_nor_cmd_auto(const spi_flash_hal_type *hal, const uint8_t *send, uint8_t send_len, uint8_t *rcv, uint8_t rcv_cnt);

	uint8_t multi_nor32_enter_a32_mode(const spi_flash_hal_type *hal);
	uint8_t multi_nor32_enter_a24_mode(const spi_flash_hal_type *hal);
	uint8_t multi_nor32_addr_mb_set(const spi_flash_hal_type *hal, uint8_t mb);
	uint8_t multi_nor32_addr_mb_get(const spi_flash_hal_type *hal);

	uint8_t multi_nor32_sector_erase(const spi_flash_hal_type *hal, uint32_t addr);
	uint8_t multi_nor32_block_erase(const spi_flash_hal_type *hal, uint32_t addr);
	uint8_t multi_nor32_block64_erase(const spi_flash_hal_type *hal, uint32_t addr);

	uint8_t multi_nor32_read(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		  
	uint8_t multi_nor32_write(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src); 
	uint8_t multi_nor32_write_multi(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

	uint8_t multi_nor32_q_read(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		
	uint8_t multi_nor32_qa_read(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		
	uint8_t multi_nor32_q_write(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src); 
	uint8_t multi_nor32_q_write_multi(const spi_flash_hal_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

	const spi_flash_hal_type * nor_hal_link(const spi_flash_hal_type *hal); 
	uint32_t nor_init(const spi_flash_hal_type *hal, uint8_t qspi_en);

	uint8_t nor_reg_get(char reg);
	uint8_t nor_reg_set(char reg, uint8_t msk, uint8_t val);

	uint32_t nor_st_read(void);		 
	uint8_t nor_busy(void);			 
	uint8_t nor_wait_for_busy(void); 

	uint8_t nor_id_read(uint8_t *des);

	void nor_write_enable(void);
	void nor_write_disable(void);

	uint8_t nor_sector_erase(uint32_t addr);
	uint8_t nor_block_erase(uint32_t addr);
	uint8_t nor_block64_erase(uint32_t addr);
	uint8_t nor_chip_erase(void);

	uint8_t nor_read(uint32_t addr, int32_t Len, uint8_t *Des);
	uint8_t nor_write(uint32_t addr, int32_t Len, const uint8_t *Src);
	uint8_t nor_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src); 

	uint8_t nor_q_read(uint32_t addr, int32_t Len, uint8_t *Des);			   
	uint8_t nor_qa_read(uint32_t addr, int32_t Len, uint8_t *Des);			   
	uint8_t nor_q_write(uint32_t addr, int32_t Len, const uint8_t *Src);	   
	uint8_t nor_q_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src); 

	uint8_t nor_security_reg_read(uint32_t addr, int32_t Len, uint8_t *Des);
	uint8_t nor_security_reg_write(uint32_t addr, int32_t Len, const uint8_t *Src);
	uint8_t nor_security_reg_erase(uint32_t addr);

	void nor_cmd_exe(uint8_t cmd);
	void nor_cmd_set(uint8_t cmd, uint8_t par);
	uint8_t nor_cmd_get(uint8_t cmd);
	uint8_t nor_cmd_auto(const uint8_t *send, uint8_t send_len, uint8_t *rcv, uint8_t rcv_cnt);

	uint8_t nor32_enter_a32_mode(void);
	uint8_t nor32_enter_a24_mode(void);
	uint8_t nor32_addr_mb_set(uint8_t mb);
	uint8_t nor32_addr_mb_get(void);

	uint8_t nor32_sector_erase(uint32_t addr);
	uint8_t nor32_block_erase(uint32_t addr);
	uint8_t nor32_block64_erase(uint32_t addr);

	uint8_t nor32_read(uint32_t addr, int32_t Len, uint8_t *Des);		 
	uint8_t nor32_write(uint32_t addr, int32_t Len, const uint8_t *Src); 
	uint8_t nor32_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src);

	uint8_t nor32_q_read(uint32_t addr, int32_t Len, uint8_t *Des);		   
	uint8_t nor32_qa_read(uint32_t addr, int32_t Len, uint8_t *Des);	   
	uint8_t nor32_q_write(uint32_t addr, int32_t Len, const uint8_t *Src); 
	uint8_t nor32_q_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src);

#ifdef __cplusplus
}
#endif

#endif 
